package com.springboot.config.redis;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.collect.Lists;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.SortingParams;
import redis.clients.jedis.Tuple;

@Component
public class CacheSingleService implements ICacheService{

	@Autowired
	private JedisPool jedisPool;

	/**
	 * 
	 * setex(写入缓存)
	 * 
	 * @param key
	 * @param seconds
	 *            过期时间 单位秒
	 * @param value
	 *            void
	 * @exception @since
	 *                1.0.0
	 */
	public String setex(String key, int seconds, String value) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.setex(key, seconds, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	/**
	 * set(key,string)
	 * @param key
	 * @param value
	 * @throws Exception
	 * @exception @since
	 *                1.0.0
	 */
	public String set(String key, String value){
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.set(key, value);
		} finally {
			returnResource(jedis);
		}
	}

	/**
	 * 
	 * set(key,byte[])
	 * 
	 * @param key
	 * @param value
	 * @throws Exception
	 *             void
	 * @exception @since
	 *                1.0.0
	 */
	public void set(byte[] key, byte[] value) throws Exception {
		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.set(key, value);
		} finally {
			returnResource(jedis);
		}
	}

	/**
	 * 
	 * get(返回指定key值)
	 * 
	 * @param key
	 * @return String
	 * @exception @since
	 *                1.0.0
	 */
	public String get(String key) {
		String value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.get(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public String getNotPre(String key) {
		String value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.get(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	/**
	 * @param key
	 * @return Set<String>
	 * @exception @since
	 *                1.0.0
	 */
	public Set<String> keys(String key) {
		Set<String> value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.keys(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public Set<String> keys(String key, String keyPre) {
		if (!StringUtils.isEmpty(keyPre)) {
			key = keyPre + key;
		}
		Set<String> value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.keys(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	/**
	 * 
	 * get(返回指定key值)
	 * 
	 * @param key
	 * @return String
	 * @exception @since
	 *                1.0.0
	 */
	public List<String> mget(String... params) {
		List<String> values = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			values = jedis.mget(params);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return values;
	}

	/**
	 * 判断是否有某个key
	 * 
	 * @param key
	 * @return String
	 * @exception @since
	 *                1.0.0
	 */
	public boolean exists(String key) {

		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.exists(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return false;
	}

	/**
	 * 
	 * get(返回指定key值)
	 * 
	 * @param key
	 * @return String
	 * @exception @since
	 *                1.0.0
	 */
	public void del(String key) {

		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.del(key.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
	}

	public void del(String key, String keyPre) {
		if (!StringUtils.isEmpty(keyPre)) {
			key = keyPre + key;
		}
		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.del(key.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
	}

	public long dels(String... keys) {
		Jedis jedis = null;
		long count = 0;
		try {
			jedis = getResource();
			count = jedis.del(keys);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return count;
	}

	/**
	 * 
	 * push(在指定链表头部增加一个或多个值，链表不存在则新建)
	 * 
	 * @param queueName
	 *            队列名
	 * @param values
	 *            值顺序列表，如：a,b,c.先进先出
	 * @return Long 队列元素个数
	 * @exception @since
	 *                1.0.0
	 */
	public Long push(String queueName, String... values) {
		Long queueLength = 0L;
		Jedis jedis = null;
		try {
			jedis = getResource();
			queueLength = jedis.lpush(queueName, values);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);

		}
		return queueLength;
	}

	/**
	 * 
	 * pop(从指定队列表尾部取出一个值)
	 * 
	 * @param queueName
	 *            队列名
	 * @return String 元素值
	 * @exception @since
	 *                1.0.0
	 */
	public String pop(String queueName) {
		String value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.rpop(queueName);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	/**
	 * 
	 * lrange(从指定队列取起始位置到结束位置元素)
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * @return List<String>
	 * @exception @since
	 *                1.0.0
	 */
	public List<String> lrange(String key, long start, long end) {

		List<String> value = Lists.newArrayList();
		;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.lrange(key, start, end);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public List<String> lrangeNotPre(String key, long start, long end) {
		List<String> value = Lists.newArrayList();
		;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.lrange(key, start, end);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	/**
	 * 
	 * lrange(从指定队列取起始位置到结束位置元素)
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * @return List<String>
	 * @exception @since
	 *                1.0.0
	 */
	public long llen(String key) {
		long value = 0L;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.llen(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public Long hset(String key, String field, String value) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.hset(key, field, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	public void hsetNotPre(String key, String field, String value) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.hset(key, field, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
	}

	public void hmset(String key, Map<String, String> value) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.hmset(key, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
	}

	public String hget(String key, String field) {

		String value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.hget(key, field);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public String hgetNotPre(String key, String field) {
		String value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.hget(key, field);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public Map<String, String> hget(String key) {

		Map<String, String> value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.hgetAll(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public List<String> hmget(String key, String... fields) {

		List<String> value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.hmget(key, fields);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	public Long hdel(String key, String... fields) {

		Long value = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.hdel(key, fields);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	/**
	 * true 存在 false 不存在
	 * 
	 * @param key
	 * @param field
	 * @return
	 */
	public boolean hexists(String key, String field) {
		boolean value = true;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.hexists(key, field);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return value;
	}

	@Override
	public boolean hincrBy(String key, String field, Long value) {
		boolean result = true;
		Jedis jedis = null;
		try {
			jedis = getResource();
			value = jedis.hincrBy(key, field, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return result;
	}

	/**
	 * queueLength(返回指定队列元素个数)
	 * @param queueName
	 * @return Long
	 * @exception @since
	 *                1.0.0
	 */
	public Long queueLength(String queueName) {
		Long queueLength = 0L;
		Jedis jedis = null;
		try {
			jedis = getResource();
			queueLength = jedis.llen(queueName);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return queueLength;
	}

	/**
	 * zadd(向有序sorts-set里添加值)
	 * @param key
	 *            指定key
	 * @param score
	 *            分数，排序用
	 * @param member
	 *            成员(要存的值) void
	 * @exception @since
	 *                1.0.0
	 */
	public Long zadd(String key, double score, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.zadd(key, score, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	/**
	 * sadd 集合(Set) (向集合添加一个或多个成员)
	 * 
	 * @param key
	 * @param member
	 */
	public Long sadd(String key, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.sadd(key, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	/**
	 * SET 集合 判断成员元素是否是集合的成员
	 * 
	 * @param key
	 * @param member
	 * @return
	 */
	public Boolean sismember(String key, String member) {
		Boolean sismember = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			sismember = jedis.sismember(key, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return sismember;
	}

	/**
	 * SET 集合 获取集合的成员
	 * 
	 * @param key
	 * @param member
	 * @return
	 */
	public Set<String> smembers(String key) {
		Set<String> sismember = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			sismember = jedis.smembers(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return sismember;
	}

	/**
	 * SET 集合 获取集合的成员
	 * 
	 * @param key
	 * @param member
	 * @return
	 */
	public Set<String> sinter(String... keys) {
		Set<String> sismember = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			sismember = jedis.sinter(keys);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return sismember;
	}

	/**
	 * 
	 * zcard(返回key Sets数量)
	 * 
	 * @param key
	 * @return Long
	 * @exception @since
	 *                1.0.0
	 */
	public Long zcard(String key) {
		Long c = 0L;
		Jedis jedis = null;
		try {
			jedis = getResource();
			c = jedis.zcard(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return c;
	}

	/**
	 * zrange(返回有序list，以score正序排，1，2，3，4等 )
	 * @param key
	 * @param start
	 * @param end
	 * @return List<String>
	 * @exception @since
	 *                1.0.0
	 */
	public Set<String> zrange(String key, final long start, final long end) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.zrange(key, start, end);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	public List<Tuple> zrangeWithScores(String key, final long start, final long end) {
		LinkedHashSet<Tuple> set = new LinkedHashSet<Tuple>();
		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.zrangeWithScores(key, start, end);
			set = (LinkedHashSet<Tuple>) jedis.zrangeWithScores(key, start, end);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return new ArrayList<Tuple>(set);
	}

	/**
	 * zrevrangeByScore(返回有续集key中score<=max并且score>=min 的元素，返回结果根据score从大到小顺序排列
	 * )
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * @return List<String>
	 * @exception @since
	 *                1.0.0
	 */
	public List<String> zrevrangeByScore(String key, final double min, final double max, int skip, int size) {
		LinkedHashSet<String> set = new LinkedHashSet<String>();
		Jedis jedis = null;
		try {
			jedis = getResource();
			set = (LinkedHashSet<String>) jedis.zrevrangeByScore(key, max, min, skip, size);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return new ArrayList<String>(set);
	}

	/**
	 * zrevrange 命令返回有序集中，指定区间内的成员。 其中成员的位置按分数值递减(从大到小)来排列。
	 * 具有相同分数值的成员按字典序的逆序(reverse lexicographical order)排列。 除了成员按分数值递减的次序排列这一点外，
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public Set<Tuple> zrevrangeWithScorese(String key, final long start, final long end) {
		Set<Tuple> set = new LinkedHashSet<Tuple>();
		Jedis jedis = null;
		try {
			jedis = getResource();
			set = jedis.zrevrangeWithScores(key, start, end);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return set;
	}

	public void zrem(String key, String... members) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			jedis.zrem(key, members);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
	}

	/**
	 * zscore(返回某个成员的分数，如果不存在返回null)
	 * @param key
	 * @param member
	 * @return Double
	 * @exception @since
	 *                1.0.0
	 */
	public Double zscore(String key, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			Double v = jedis.zscore(key, member);
			return v;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	/**
	 * 有序集合中指定成员的分数加上增量
	 * @param key
	 * @param score
	 * @param member
	 * @return
	 */
	public Double zincrby(String key, double score, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			Double v = jedis.zincrby(key, score, member);
			return v;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	/**
	 * incr(按key自增(+1))
	 * @param key
	 * @return Long
	 * @exception @since
	 *                1.0.0
	 */
	public Long incr(String key) {
		Long i = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			i = jedis.incr(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return i;
	}

	public Long incrBy(String key, long increament) {
		Long i = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			i = jedis.incrBy(key, increament);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return i;
	}

	/**
	 * redis锁
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public Long setnx(String key, String value) {
		Long i = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			i = jedis.setnx(key, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return i;
	}

	public void returnResource(Jedis jedis) {
		jedisPool.returnResource(jedis);
	}

	public Jedis getResource() {
		Jedis jedis = jedisPool.getResource();
		return jedis;
	}

	/**
	 * 存放List
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public Long rpush(String key, String value) {
		Long count = 0L;
		Jedis jedis = null;
		try {
			jedis = getResource();
			count = jedis.rpush(key, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return count;
	}

	/**
	 * 获取List
	 * 
	 * @param key
	 * @param start
	 * @param count
	 *            -1为全部
	 * @return
	 */
	public List<String> sort(String key, int start, int count) {
		List<String> list = null;
		Jedis jedis = null;
		try {
			jedis = getResource();
			SortingParams sortingParams = new SortingParams();
			sortingParams.alpha();
			sortingParams.desc();
			// sortingParams.asc();
			sortingParams.limit(start, count);
			list = jedis.sort(key, sortingParams);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return list;
	}

	/**
	 * 发布
	 * 
	 * @param channel
	 * @param message
	 * @return
	 */
	public Long publish(String channel, String message) {
		Long result = 0L;
		Jedis jedis = null;
		try {
			jedis = getResource();
			result = jedis.publish(channel, message);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return result;
	}

	/**
	 * 获取值过期时间
	 * 
	 * @param key
	 * @return
	 */
	public Long ttl(String key) {
		Long result = 0L;
		Jedis jedis = null;
		try {
			jedis = getResource();
			result = jedis.ttl(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return result;
	}

	@Override
	public Double zincress(String key, double score, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.zincrby(key, score, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	@Override
	public Long smove(String srckey, String dstkey, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.smove(srckey, dstkey, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	@Override
	public Long scard(String key) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.scard(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	@Override
	public List<String> srandmember(String key, int count) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.srandmember(key, count);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}
	
	@Override
	public Long zrevrank(String key, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.zrevrank(key, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return null;
	}

	@Override
	public long hlen(String key) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.hlen(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return 0;
	}

	@Override
	public Long srem(String key, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.srem(key, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return 0L;
	}

	@Override
	public Long zrem(String key, String member) {
		Jedis jedis = null;
		try {
			jedis = getResource();
			return jedis.zrem(key, member);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			returnResource(jedis);
		}
		return 0L;
	}
}
